let currentUser = { user: "Peter", roles: [{ role: "user" }, { role: "admin" }] };

function isInRole(role : string) :boolean{
    return currentUser.roles.some(r => r.role === role)
}

function Role(role :string){
    return function(target: any, propertyKey : string | symbol,descriptor :PropertyDescriptor){
        let originalMethod = descriptor.value;
        descriptor.value = function(){
            if(isInRole(role)){
                originalMethod.apply(this, arguments)
            }else{
                console.log(`${currentUser.user} is not in the ${role} role`);
            }
            return descriptor;
        }
    }
}

interface IDecoratorExampe {
    AnyoneCanRun(args : string) : void;
    AdminOnly(args:string) :void;
}

class NoRoleCheck implements IDecoratorExampe{
    AnyoneCanRun(args: string){
        console.log(args)
    }
    AdminOnly(args :string){
        console.log(args)
    }
}

class DecoratedExample implements IDecoratorExampe{
    @Role("user")
    AnyoneCanRun(args : string){
        console.log(args)
    }
    @Role("admin")
    AdminOnly(args :string){
        console.log(args)
    }
}

function Test(decoratorMethod:IDecoratorExampe) {
    console.log(`current user ${currentUser.user}`)    
    decoratorMethod.AdminOnly("Run as admin")
    decoratorMethod.AnyoneCanRun("Run as user") 
}

Test(new NoRoleCheck());
Test(new DecoratedExample())
currentUser = {user: "bob", roles : [{role:"user"}] };
Test(new DecoratedExample())
Test(new NoRoleCheck())